//! \file file.hpp
//! \brief Purewell Library File Header
//! \author Yubin Lim (purewell@gmail.com)
//! \since 2008-01-25

#ifndef __PWHDR_FILE_HPP__
#define __PWHDR_FILE_HPP__

#include <string>

namespace purewell
{

class PWFileUtil;
class PWIOPoll;

//! \brief File handler.
class PWAPI PWFile
{
public:
	//! \brief Get file descriptor.
	//! \return File descriptor.
	inline int getHandle(void) const
	{
		return m_fd;
	}

	//! \brief Destroy.
	virtual void destroy(void);

	//! \brief Attach file descriptor.
	//! \return On success, true.
	virtual bool attach(int fd);

	//! \brief Detach file descriptor.
	//! \return Detached file descriptor.
	virtual int detach(void);

	//! \brief Read data from file descriptor.
	//! \param[out] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \return On success, read size. In case of error, it returns -1.
	virtual ssize_t read(void* buf, size_t blen);

	//! \brief Read data from file descriptor parallely.
	//! \param[out] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \param[in] offset Offset to read.
	//! \return On success, read size. In case of error, it returns -1.
	virtual ssize_t readParallel(void* buf, size_t blen, off_t offset);

	//! \brief Write data to file descriptor.
	//! \param[in] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \return On success, written size. In case of error, it returns -1.
	virtual ssize_t write(const void* buf, size_t blen);

	//! \brief Write data to file descriptor parallely.
	//! \param[in] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \param[in] offset Offset to write.
	//! \return On success, read size. In case of error, it returns -1.
	virtual ssize_t writeParallel(const void* buf, size_t blen,
		off_t offset);

public:
	// File controls

	//! \brief Set blocking mode.
	//! \param[in] block Blocking mode.
	//! \return On success, true.
	virtual bool setModeBlock(bool block);

	//! \brief Get blocking mode.
	//! \param[out] block Blocking mode.
	//! \return On success, true.
	virtual bool getModeBlock(bool& block) const;

	//! \brief Set asynchronous mode.
	//! \param[in] async Asynchronous mode.
	//! \return On success, true.
	virtual bool setModeAsync(bool async);

	//! \brief Get asynchronous mode.
	//! \param[out] block Asynchronous mode.
	//! \return On success, true.
	virtual bool getModeAsync(bool& block) const;

	//! \brief Set mode close on exec.
	//! \param[in] coe Close on exec mode.
	//! \return On success, true.
	virtual bool setModeCloseOnExec(bool coe);

	//! \brief Get mode close on exec.
	//! \param[out] coe Close on exec mode.
	//! \return On success, true.
	virtual bool getModeCloseOnExec(bool& coe) const;

	//! \brief Set mode.
	//! \param[in] mode Mode flags.
	//! \return On success, true.
	virtual bool setMode(int mode);

	//! \brief Get mode.
	//! \param[out] mode Mode flags.
	//! \return On success, true.
	virtual bool getMode(int& mode) const;

	//! \brief Duplicate file descriptor.
	//! \param[in] srcfd Source file descriptor.
	//! \return On success, true.
	//! \warning Without destroy method, initialized file descriptor will be leaked.
	virtual bool duplicate(int srcfd);

	//! \brief Duplicate file descriptor.
	//! \param[in] srcfd Source file descriptor.
	//! \param[in] newfd New file descriptor to allocate.
	//! \return On success, true.
	//! \warning Without destroy method, initialized file descriptor will be leaked.
	virtual bool duplicate(int srcfd, int newfd);

public:
	//! \brief Callback-interface for PWIOPoll.
	//! \param[in,out] io Caller.
	//! \param[in] fd File descriptor.
	//! \param[in] event Events.
	virtual void onEvent(PWIOPoll* io, int fd, int event);

public:
	explicit PWFile();
	virtual ~PWFile();

private:
	explicit PWFile(const PWFile&) {}
	PWFile& operator = (const PWFile&) {return *this;}

protected:
	int			m_fd;	//!< File descriptor.

	friend class PWFileUtil;
};

//! \brief Named file interface.
class PWAPI PWNamedFile : public PWFile
{
public:
	//! \brief Initialize file object.
	//! \param[in] name File name.
	//! \param[in] flag Open flag.
	//! \param[in] perm Permittion.
	//! \return On success, true.
	virtual bool initialize(const char* name, int flag, int perm);

	//! \brief Get name.
	//! \return Name string(C-style).
	const char* getName(void) const;

	virtual int detach(void);

	//! \brief Unlink file.
	//! \return On success, true.
	virtual bool unlink(void);

public:
	explicit PWNamedFile();
	virtual ~PWNamedFile();

protected:
	std::string m_name;		//!< File name.

	friend class PWFileUtil;
};

//! \brief File flags.
class PWAPI PWFileFlag
{
public:
	//! \brief Get flags.
	//! \return Flags.
	int getFlags(void) const;

	//! \brief Set flags.
	//! \param[in] flags Flags.
	//! \return Flags.
	int setFlags(int flags);

	//! \brief Set RW mode.
	//! \param[in] mode PWIO_R, PWIO_W or both of all.
	//! \return On success, true.
	bool setRWMode(int mode);

	//! \brief Get RW mode.
	//! \return RW mode.
	int getRWMode(void) const;

	//! \brief Set/unset create flag.
	//! \param[in] v Flag.
	//! \return Result of set or unset.
	bool setCreate(bool v);

	//! \brief Set/unset exclusive flag.
	//! \param[in] v Flag.
	//! \return Result of set or unset.
	bool setExclusive(bool v);

	//! \brief Set/unset truncate flag.
	//! \param[in] v Flag.
	//! \return Result of set or unset.
	bool setTruncate(bool v);

	//! \brief Set/unset append flag.
	//! \param[in] v Flag.
	//! \return Result of set or unset.
	bool setAppend(bool v);

	//! \brief Set/unset nonblock flag.
	//! \param[in] v Flag.
	//! \return Result of set or unset.
	bool setNonblock(bool v);

	//! \brief Set/unset sync flag.
	//! \param[in] v Flag.
	//! \return Result of set or unset.
	bool setSync(bool v);

	//! \brief Check create flag.
	//! \return On set, true.
	bool isCreate(void) const;

	//! \brief Check exclusive flag.
	//! \return On set, true.
	bool isExclusive(void) const;

	//! \brief Check truncate flag.
	//! \return On set, true.
	bool isTruncate(void) const;

	//! \brief Check append flag.
	//! \return On set, true.
	bool isAppend(void) const;

	//! \brief Check nonblock flag.
	//! \return On set, true.
	bool isNonblock(void) const;

	//! \brief Check sync flag.
	//! \return On set, true.
	bool isSync(void) const;

	//! \brief Check read-only flag.
	//! \return On set, true.
	bool isReadOnly(void) const;

	//! \brief Check write-only flag.
	//! \return On set, true.
	bool isWriteOnly(void) const;

	//! \brief Check read & write flag.
	//! \return On set, true.
	bool isReadAndWrite(void) const;

	//! \brief Swap.
	//! \param[out] obj Object to swap.
	void swap(PWFileFlag& obj);

public:
	operator int (void) const;
	PWFileFlag& operator = (int flags);
	PWFileFlag& operator = (const PWFileFlag& flag);

	bool operator == (int flags) const;
	bool operator == (const PWFileFlag& flag) const;
	bool operator != (int flags) const;
	bool operator != (const PWFileFlag& flag) const;

public:
	explicit PWFileFlag();
	explicit PWFileFlag(int flags);
	explicit PWFileFlag(const PWFileFlag& flag);
	virtual ~PWFileFlag();

private:
	int		m_flags;
};

//! \brief File access mode.
class PWAPI PWFileAccessMode
{
public:
	//! \brief Get mode.
	//! \return Mode.
	int getMode(void) const;

	//! \brief Set mode.
	//! \param[in] mode Mode.
	//! \return Mode.
	int setMode(int mode);

	//! \brief Set owner-read permission.
	//! \param[in] v Set/unset permission.
	//! \return Permission.
	bool setOwnerRead(bool v);

	//! \brief Set owner-write permission.
	//! \param[in] v Set/unset permission.
	//! \return Permission.
	bool setOwnerWrite(bool v);

	//! \brief Set owner-execute permission.
	//! \param[in] v Set/unset permission.
	//! \return Permission.
	bool setOwnerExecute(bool v);

	//! \brief Set group-read permission.
	//! \param[in] v Set/unset permission.
	//! \return Permission.
	bool setGroupRead(bool v);

	//! \brief Set group-write permission.
	//! \param[in] v Set/unset permission.
	//! \return Permission.
	bool setGroupWrite(bool v);

	//! \brief Set group-execute permission.
	//! \param[in] v Set/unset permission.
	//! \return Permission.
	bool setGroupExecute(bool v);

	//! \brief Set guest-read permission.
	//! \param[in] v Set/unset permission.
	//! \return Permission.
	bool setGuestRead(bool v);

	//! \brief Set guest-write permission.
	//! \param[in] v Set/unset permission.
	//! \return Permission.
	bool setGuestWrite(bool v);

	//! \brief Set guest-execute permission.
	//! \param[in] v Set/unset permission.
	//! \return Permission.
	bool setGuestExecute(bool v);

	//! \brief Check owner-read permission.
	//! \return Permission.
	bool isOwnerRead(void) const;

	//! \brief Check owner-write permission.
	//! \return Permission.
	bool isOwnerWrite(void) const;

	//! \brief Check owner-execute permission.
	//! \return Permission.
	bool isOwnerExecute(void) const;

	//! \brief Check group-read permission.
	//! \return Permission.
	bool isGroupRead(void) const;

	//! \brief Check group-write permission.
	//! \return Permission.
	bool isGroupWrite(void) const;

	//! \brief Check group-execute permission.
	//! \return Permission.
	bool isGroupExecute(void) const;

	//! \brief Check guest-read permission.
	//! \return Permission.
	bool isGuestRead(void) const;

	//! \brief Check guest-write permission.
	//! \return Permission.
	bool isGuestWrite(void) const;

	//! \brief Check guest-execute permission.
	//! \return Permission.
	bool isGuestExecute(void) const;

public:
	operator int (void) const;
	PWFileAccessMode& operator = (int mode);
	PWFileAccessMode& operator = (const PWFileAccessMode& obj);

	bool operator == (int mode) const;
	bool operator == (const PWFileAccessMode& obj) const;

	bool operator != (int mode) const;
	bool operator != (const PWFileAccessMode& obj) const;

public:
	explicit PWFileAccessMode();
	explicit PWFileAccessMode(int mode);
	explicit PWFileAccessMode(const PWFileAccessMode& obj);
	virtual ~PWFileAccessMode();

public:
	int		m_mode;
};

};

#endif//!__PWHDR_FILE_HPP__

